#include <iostream>
#include <string>
#include <gmp.h>
#include <gmpxx.h>
#include <string>
#include <fstream>
#include <sstream>

#define BITS_PER_DIGIT 3.32192809488736234787;

void borwein1985() {
	mpf_class *a0, *a1, *y0, *y1, *pi0, *pi1;
	mpf_class eq_cmp("1E-10000000");
	mpf_class pow2k3(8);

	int cmpr;
	int iteration = 0;

	{
		mpf_class tmp = 2;
		tmp = sqrt(tmp);

		a0 = new mpf_class(6 - 4 * tmp);
		y0 = new mpf_class(tmp - 1);
		pi0 = new mpf_class(1 / *a0);
	}
	

	a1 = new mpf_class();
	y1 = new mpf_class();
	pi1 = new mpf_class();

	do {

		std::stringstream ss;
		ss << "BST_Iteracao_" << iteration << ".txt";
		std::fstream file;
		file.open(ss.str().c_str(), std::fstream::out);
		file.setf(std::ios::fixed, std::ios::floatfield);
		file.precision(10000000);
		file << *pi0 << std::endl;

		std::cout << "Comecando a calcular a iteracao " << ++iteration << std::endl;

		{
			mpf_class tmp = *y0 * *y0;
			tmp = sqrt(sqrt(1 - tmp * tmp));
			*y1 = (1 - tmp) / (1 + tmp);
			tmp = 1 + *y1;
			tmp = tmp * tmp;
			tmp = tmp * tmp;
			*a1 = *a0 * tmp - pow2k3 * *y1 * (1 + *y1 + *y1 * *y1);
			pow2k3 *= 4;
			*pi1 = 1 / *a1;
		}

		cmpr = cmp(abs(*pi1 - *pi0), eq_cmp);


		std::swap(a0, a1);
		std::swap(y0, y1);
		std::swap(pi0, pi1);

	} while (cmpr >= 0);

	{
		std::stringstream ss;
		ss << "BST_Iteracao_" << iteration << "_PI_FINAL.txt";
		std::fstream file;
		file.open(ss.str().c_str(), std::fstream::out);
		file.setf(std::ios::fixed, std::ios::floatfield);
		file.precision(10000000);
		file << *pi0 << std::endl;
	}

	delete a0;
	delete a1;
	delete y0;
	delete y1;
	delete pi0;
	delete pi1;
	std::cout << "PI calculado com sucesso\n";
}

int main(int argc, char *argv[]) {
	mpf_set_default_prec((long int)(3.32192809488736234787 * 10000100.0));

	std::cout << "Bem vindo ao programa que calcula o PI!\n";
	std::cout << "10 milhoes de casas do pi serao calculadas!\n";
	std::cout << "Arquivos de prefixo \"BST_\" serao criados\n";

	// std::cout.setf(std::ios::fixed, std::ios::floatfield);
	// std::cout.precision(10000000);

	borwein1985();
	return 0;
}
